package com.edmendst.xmall.service.impl;

import com.edmendst.xmall.dto.ProductCategory;
import com.edmendst.xmall.dto.ProductSellInfo;
import com.edmendst.xmall.mapper.CategoryMapper;
import com.edmendst.xmall.mapper.ProductImageMapper;
import com.edmendst.xmall.mapper.ProductMapper;
import com.edmendst.xmall.mapper.ShopMapper;
import com.edmendst.xmall.pojo.*;
import com.edmendst.xmall.service.ProductService;
import com.edmendst.xmall.service.ShopService;
import com.edmendst.xmall.service.UserService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class ProductServiceImpl implements ProductService {

    @Value("${product.image}")
    private String productImage;

    @Value("${product.video}")
    private String productVideo;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private ProductImageMapper productImageMapper;

    @Autowired
    private ShopMapper shopMapper;

    @Autowired
    private ShopService shopService;

    @Autowired
    private CategoryServiceImpl categoryService;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisTemplate redisTemplate;

    private static final String PRODUCT_HASH_PREFIX = "product:detail:";
    private static final String PRODUCT_IMAGE_HASH_PREFIX = "product:images:";


    @Override
    public String updateProductCategory(ProductCategory productCategory) {
        Category category = new Category();
        category.setCategoryName(productCategory.getCategoryName());

        // 新增null值校验逻辑
        if (productCategory.getParentId() == null || productCategory.getParentId() == 0) {
            category.setParentId(null); // 强制顶级分类parent_id为null
            categoryMapper.insert(category);
            return "创建顶级分类成功";
        }

        // 强制校验parentId合法性
        if (productCategory.getParentId() == null) {
            return "父分类ID不能为空";
        }


        // 处理0级分类
        if (productCategory.getParentId() == 0) {
            category.setParentId(0);
            categoryMapper.insert(category);
            return "创建顶级分类成功";
        }

        // 校验父分类必须存在
        Category parent = categoryMapper.selectByPrimaryKey(productCategory.getParentId());
        if (parent == null) {
            return "指定的父分类不存在";
        }

        category.setParentId(productCategory.getParentId());
        categoryMapper.insertSelective(category);
        return "创建子分类成功";
    }

    @Override
    public List<Category> selectProductCategoryOfTop() {
        CategoryExample example = new CategoryExample();
        example.createCriteria().andParentIdIsNull(); // 改为查询parent_id IS NULL
        return categoryMapper.selectByExample(example);
    }


    @Override
    public int deleteProductCategoryName(Integer categoryId) {
        int i = categoryMapper.deleteByPrimaryKey(categoryId);

        if (i == 1) {
            String categoryKey = "product:category:" + categoryId + ":ids";
            redisTemplate.delete(categoryKey);
            return 1;
        }
        return 0;
    }


    @Override
    @Transactional
    public String productSell(ProductSellInfo productSellInfo, List<MultipartFile> productCoverImage) {
        Product product = new Product();
        product.setProductName(productSellInfo.getProductName());
        product.setProductDescription(productSellInfo.getProductDescription());
        product.setProductPrice(productSellInfo.getProductPrice());
        product.setProductStock(productSellInfo.getProductStock());
        product.setCategoryId(productSellInfo.getCategoryId());
        product.setShopId(productSellInfo.getShopId());
        product.setProductIsOnline(false);// 默认下架状态

        int i = productMapper.insertSelective(product);// 确保返回主键

        Integer productId = product.getProductId();

        //上传商品介绍图片
        String uploaded = uploadProductImageAndVideo(productCoverImage, productId);

        // 清除卖家缓存和分类缓存
        String sellerKey = "product:shop:" + productSellInfo.getShopId() + ":ids";
        redisTemplate.delete(sellerKey);
        String categoryKey = "product:category:" + productSellInfo.getCategoryId() + ":ids";
        redisTemplate.delete(categoryKey);
// 清除全局推荐缓存
        redisTemplate.delete("product:online:list");

        redisTemplate.delete("product:all:ids");

        if (i == 1 && uploaded != null) {
            return "上传成功" + uploaded;
        } else if (i != 1) {
            return "商品信息上传失败";
        } else {
            return "图片上传失败" + uploaded;
        }
    }

    @Override
    public int deleteProduct(Integer productId, String username) {
        // 检查productId是否有效
        if (productId == null || productId <= 0) {
            throw new IllegalArgumentException("无效的productId");
        }

        Product product = productMapper.selectByPrimaryKey(productId);
        if (product == null) {
            throw new IllegalArgumentException("商品不存在");
        }

        Integer userIdByUserName = userService.selectUserIdByUserName(username);
        Integer shopId1 = productMapper.selectByPrimaryKey(productId).getShopId();

        ShopExample shopExample = new ShopExample();
        shopExample.createCriteria().andUserIdEqualTo(userIdByUserName);
        Integer shopId = shopMapper.selectByExample(shopExample).get(0).getShopId();

        ProductImageExample  productImageExample = new ProductImageExample();
        productImageExample.createCriteria().andProductIdEqualTo(productId);

        if (product == null) {
            return 0;
        }

        if (Objects.equals(shopId, shopId1)) {

            productImageMapper.deleteByExample(productImageExample);
            productMapper.deleteByPrimaryKey(productId);

            String categoryKey = "product:category:" + product.getCategoryId() + ":ids";
            redisTemplate.opsForSet().remove(categoryKey, productId.toString());
            String sellerKey = "product:shop:" + product.getShopId() + ":ids";
            redisTemplate.delete(sellerKey);
            redisTemplate.delete(PRODUCT_HASH_PREFIX + productId);
            redisTemplate.opsForSet().remove("product:all:ids", productId.toString());
            redisTemplate.delete("product:online:list"); // 清除推荐列表缓存
            return 1;
        }
        return 0;
    }

    public String uploadProductImageAndVideo(List<MultipartFile> productCoverImage, Integer productId) {
        List<String> uploaded = new ArrayList<>();
        int i = 0;
        String coverImage = null;
        final String[] ALLOWED_EXT = {".png", ".jpg", ".jpeg", ".gif"};

        for (MultipartFile multipartFile : productCoverImage) {
            if (multipartFile.isEmpty() || multipartFile==null || multipartFile.getSize() == 0) {
                continue;
            }
            try {
                // 校验文件类型
                String fileName = multipartFile.getOriginalFilename();
                String fileExt = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
                if (!Arrays.asList(ALLOWED_EXT).contains(fileExt)) {
                    throw new IllegalArgumentException("不支持的文件类型");
                }

                // 构建存储目录
                Path targetDir = Paths.get(productImage, productId.toString());
                Files.createDirectories(targetDir);

                // 生成唯一文件名
                String newFileName = UUID.randomUUID() + fileExt;
                Path targetPath = targetDir.resolve(newFileName);

                // 保存文件
                try (InputStream is = multipartFile.getInputStream()) {
                    Files.copy(is, targetPath, StandardCopyOption.REPLACE_EXISTING);
                }

                // 保存相对路径到数据库
                String relativePath = productId + "/" + newFileName;
                ProductImage productImage = new ProductImage();
                productImage.setProductId(productId);
                productImage.setImageUrl(relativePath);//  只保存相对路径
                productImage.setSortOrder(i);
                productImageMapper.insertSelective(productImage);

                // 如果是第一张图片，设置为封面
                if (i == 0) {
                    coverImage = relativePath;
                    Product product = new Product();
                    product.setProductId(productId);
                    product.setProductCoverImage(coverImage);
                    productMapper.updateByPrimaryKeySelective(product);
                    // 清除商品缓存
                    redisTemplate.delete(PRODUCT_HASH_PREFIX + productId);
                }

                // 清除图片缓存
                String imageSetKey = PRODUCT_IMAGE_HASH_PREFIX + productId;
                redisTemplate.delete(imageSetKey);
                i++;


            } catch (Exception e) {
                return "失败原因：" + e.getMessage();
            }
        }
        return "上传成功，共" + i + "张图片";
    }

    //    @Cacheable(value = "productCache", key = "#categoryId")
    @Override
    public <SortedSetOperations> List<ProductSellInfo> selectProductByCategoryId(Integer categoryId) {
        String categorySetKey = "product:category:" + categoryId + ":ids";

        // 从 Redis 缓存中读取商品 ID 列表
        SetOperations<String, String> setOperations = redisTemplate.opsForSet();
        Set<String> cachedProductIds = setOperations.members(categorySetKey);

        if (cachedProductIds != null && !cachedProductIds.isEmpty()) {

            if (cachedProductIds.contains("EMPTY")) {
                return Collections.emptyList();
            }

            List<ProductSellInfo> productSellInfos = new ArrayList<>();
            for (String productId : cachedProductIds) {

                if ("EMPTY".equals(productId)) continue;

                String productHashKey = PRODUCT_HASH_PREFIX + productId;
                HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash();

                // 从 Hash 中读取商品详情
                // 读取时转换类型
                Map<String, Object> entries = hashOps.entries(productHashKey);
                if (entries != null && !entries.isEmpty()) {
                    String isOnlineStr = (String) entries.get("productIsOnline");
                    Boolean isOnline = "1".equals(isOnlineStr);
                    if (isOnline != null && isOnline) {
                        ProductSellInfo productSellInfo = new ProductSellInfo();
                        productSellInfo.setProductId(Integer.parseInt((String) entries.get("productId")));
                        productSellInfo.setProductName((String) entries.get("productName"));
                        productSellInfo.setProductDescription((String) entries.get("productDescription"));
                        productSellInfo.setProductPrice(new BigDecimal((String) entries.get("productPrice")));
                        productSellInfo.setProductStock(Integer.parseInt((String) entries.get("productStock")));
                        productSellInfo.setCategoryId(Integer.parseInt((String) entries.get("categoryId")));
                        productSellInfo.setShopId(Integer.parseInt((String) entries.get("shopId")));
                        productSellInfo.setProductCoverImage((String) entries.get("productCoverImage"));

                        String productImageSetKey = PRODUCT_IMAGE_HASH_PREFIX + productId;
                        ZSetOperations<String, String> productImageSetOps = redisTemplate.opsForZSet();
                        Set<ZSetOperations.TypedTuple<String>> productImageSets = productImageSetOps.rangeWithScores(productImageSetKey, 0, -1);
                        if (productImageSets != null && !productImageSets.isEmpty()) {
                            for (ZSetOperations.TypedTuple<String> productImageSet : productImageSets) {
                                String imageUrl = productImageSet.getValue();
                                productSellInfo.getProductImageList().add(imageUrl);
                                productSellInfo.getProductImageListOrder().add(productImageSet.getScore().intValue());
                            }
                        }
                        productSellInfo.setProductImageListOrder(new ArrayList<>());
                        productSellInfo.setProductImageList(new ArrayList<>());


                        productSellInfos.add(productSellInfo);
                    }
                }
            }
            return productSellInfos;
        }


        //如果缓存未命中，则从数据库查询
        ProductExample example = new ProductExample();
        example.createCriteria().andCategoryIdEqualTo(categoryId);

        List<Product> products = productMapper.selectByExampleWithBLOBs(example);
        List<ProductSellInfo> sellInfoList = products
                .stream()
                .filter(product -> Boolean.TRUE.equals(product.getProductIsOnline())) // 过滤出已上架的商品
                .map(product -> {
                    ProductSellInfo info = new ProductSellInfo();
                    info.setProductId(product.getProductId());
                    info.setProductName(product.getProductName());
                    info.setProductDescription(product.getProductDescription());
                    info.setProductPrice(product.getProductPrice());
                    info.setProductStock(product.getProductStock());
                    info.setCategoryId(product.getCategoryId());
                    info.setShopId(product.getShopId());
                    info.setProductCoverImage(product.getProductCoverImage());

                    ProductImageExample productImageExample = new ProductImageExample();
                    productImageExample.createCriteria().andProductIdEqualTo(product.getProductId());
                    List<ProductImage> productImages = productImageMapper.selectByExample(productImageExample);
                    productImages.forEach(productImage -> {
                        info.getProductImageList().add(productImage.getImageUrl());
                        info.getProductImageListOrder().add(productImage.getSortOrder());
                    });

                    info.setProductOnlineStatus(product.getProductIsOnline() ? 1 : 0); // Boolean转Integer
//                    System.out.println(info);
                    return info;
                })
                .toList();


        redisTemplate.delete(categorySetKey); //先删除旧数据

        // 写入 Redis 缓存
        if (sellInfoList.isEmpty()) {
            // 缓存空值防穿透
            redisTemplate.opsForSet().add(categorySetKey, "EMPTY");
            redisTemplate.expire(categorySetKey, 1, TimeUnit.MINUTES);
        } else {
            HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash();
            for (ProductSellInfo info : sellInfoList) {
                String id = info.getProductId().toString();
                String productHashKey = PRODUCT_HASH_PREFIX + id;

                // 存储商品详情到 Hash
                hashOps.putAll(productHashKey, Map.of(
                        "productId", info.getProductId().toString(),
                        "productName", info.getProductName(),
                        "productDescription", info.getProductDescription(),
                        "productPrice", info.getProductPrice().toString(),
                        "productStock", info.getProductStock().toString(),
                        "categoryId", info.getCategoryId().toString(),
                        "shopId", info.getShopId().toString(),
                        "productCoverImage", info.getProductCoverImage(),
                        "productIsOnline", info.getProductOnlineStatus().toString()

                ));

                String imageSetKey = "product:image:" + id;
                ZSetOperations<String, String> zSetOps = redisTemplate.opsForZSet();
                redisTemplate.delete(imageSetKey);

                List<String> productImageList = info.getProductImageList();
                List<Integer> productImageListOrder = info.getProductImageListOrder();
                for (int i = 0; i < productImageList.size(); i++) {
                    zSetOps.add(imageSetKey, productImageList.get(i), (double) productImageListOrder.get(i));
                }
                redisTemplate.expire(imageSetKey, 10, TimeUnit.MINUTES);

                // 将商品 ID 添加到 Set 中
                setOperations.add(categorySetKey, id);
            }

            // 设置 Set 过期时间
            redisTemplate.expire(categorySetKey, 10, TimeUnit.MINUTES);

        }
        return sellInfoList;
    }

    @Override
    public List<ProductSellInfo> getProductBySeller(Integer shopId) {

        int shopIdByUsername = shopId;

        String sellerProductSetKey = "product:shop:" + shopIdByUsername + ":ids";

        Set<String> cachedProductIds = redisTemplate.opsForSet().members(sellerProductSetKey);

        if (redisTemplate.hasKey(sellerProductSetKey)) {

            if (cachedProductIds != null && !cachedProductIds.isEmpty()) {
                List<ProductSellInfo> productSellInfos = new ArrayList<>();
                for (String productId : cachedProductIds) {

                    HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash();
                    String productHashKey = PRODUCT_HASH_PREFIX + productId;

                    Map<String, Object> entries = hashOps.entries(productHashKey);

                    if (entries != null && !entries.isEmpty()) {
                        ProductSellInfo productSellInfo = new ProductSellInfo();
                        productSellInfo.setProductId(Integer.parseInt((String) entries.get("productId")));
                        productSellInfo.setProductName((String) entries.get("productName"));
                        productSellInfo.setProductDescription((String) entries.get("productDescription"));
                        productSellInfo.setProductPrice(new BigDecimal((String) entries.get("productPrice")));
                        productSellInfo.setProductStock(Integer.parseInt((String) entries.get("productStock")));
                        productSellInfo.setCategoryId(Integer.parseInt((String) entries.get("categoryId")));
                        productSellInfo.setShopId(Integer.parseInt((String) entries.get("shopId")));
                        productSellInfo.setProductCoverImage((String) entries.get("productCoverImage"));
                        productSellInfos.add(productSellInfo);
                    }

                }
                return productSellInfos;
            }
        }

        ProductExample productExample = new ProductExample();
        productExample.createCriteria().andShopIdEqualTo(shopIdByUsername);
        List<Product> products = productMapper.selectByExampleWithBLOBs(productExample);

        List<ProductSellInfo> productSellInfos = new ArrayList<>();
        Set<String> cachedProductIdsTemp = new HashSet<>();

        if (!products.isEmpty()) {
            for (Product product : products) {
                ProductSellInfo info = new ProductSellInfo();
                info.setProductId(product.getProductId());
                info.setProductName(product.getProductName());
                info.setProductDescription(product.getProductDescription());
                info.setProductPrice(product.getProductPrice());
                info.setProductStock(product.getProductStock());
                info.setCategoryId(product.getCategoryId());
                info.setShopId(product.getShopId());
                info.setProductCoverImage(product.getProductCoverImage());
                info.setProductOnlineStatus(product.getProductIsOnline() ? 1 : 0);
                productSellInfos.add(info);


                String productHashKey = "product:detail:" + info.getProductId();
                HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash();
                hashOps.putAll(productHashKey, Map.of(
                        "productId", info.getProductId().toString(),
                        "productName", info.getProductName(),
                        "productDescription", info.getProductDescription(),
                        "productPrice", info.getProductPrice().toString(),
                        "productStock", info.getProductStock().toString(),
                        "categoryId", info.getCategoryId().toString(),
                        "shopId", info.getShopId().toString(),
                        "productCoverImage", info.getProductCoverImage(),
                        "productIsOnline", info.getProductOnlineStatus().toString()
                ));

                cachedProductIdsTemp.add(info.getProductId().toString());

            }

            // 保存产品 ID 集合到 Redis 并设置过期时间
            redisTemplate.opsForSet().add(sellerProductSetKey, cachedProductIdsTemp.toArray(new String[0]));
            redisTemplate.expire(sellerProductSetKey, 10, TimeUnit.MINUTES);

            return productSellInfos;

        } else {
            // 缓存空值防穿透
            redisTemplate.opsForSet().add(sellerProductSetKey, "EMPTY");
            redisTemplate.expire(sellerProductSetKey, 1, TimeUnit.MINUTES);
            return List.of();
        }

    }

    //编辑商品价格（限售卖方）
    @Override
    public String updateProductPrice(Integer productId, BigDecimal productPrice, String username) {
        int shopIdByUsername = shopService.selectShopIdByUsername(username);
        ProductExample productExample = new ProductExample();
        productExample.createCriteria().andProductIdEqualTo(productId);
        Product product1 = productMapper.selectByExample(productExample).get(0);
        if (product1.getShopId().equals(shopIdByUsername)) {
            Product product = new Product();
            product.setProductPrice(productPrice);
            productMapper.updateByExampleSelective(product, productExample);

            //  更新缓存
            String productHashKey = PRODUCT_HASH_PREFIX + productId;
            HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash();
            hashOps.put(productHashKey, "productPrice", productPrice.toString());

            if (redisTemplate.hasKey(productHashKey)) {
                redisTemplate.expire(productHashKey, 10, TimeUnit.MINUTES);
            }

            return "修改成功";
        }
        return "未查询到商品信息";
    }

    //编辑商品介绍（限售卖方）
    @Override
    public String updateProductDescription(Integer productId, String productDescription, String username) {
        int shopIdByUsername = shopService.selectShopIdByUsername(username);
        ProductExample productExample = new ProductExample();
        productExample.createCriteria().andProductIdEqualTo(productId);
        Product product1 = productMapper.selectByExample(productExample).get(0);
        if (product1.getShopId().equals(shopIdByUsername)) {
            Product product = new Product();
            product.setProductDescription(productDescription);
            productMapper.updateByExampleSelective(product, productExample);

            //  更新缓存
            String productHashKey = PRODUCT_HASH_PREFIX + productId;
            HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash();
            hashOps.put(productHashKey, "productDescription", productDescription);

            if (redisTemplate.hasKey(productHashKey)) {
                redisTemplate.expire(productHashKey, 10, TimeUnit.MINUTES);
            }
            return "修改成功";
        }
        return "未查询到商品信息";
    }

    // 查询商品库存
    @Override
    // 添加缓存逻辑
//    @Cacheable(value = "productCache", key = "#productId")
    public ProductSellInfo getStock(Integer productId) {
        ProductExample example = new ProductExample();
        example.createCriteria().andProductIdEqualTo(productId);
        Product product = productMapper.selectByExample(example).get(0);
        ProductSellInfo productSellInfo = new ProductSellInfo();
        productSellInfo.setProductName(product.getProductName());
        productSellInfo.setProductStock(product.getProductStock());
        productSellInfo.setProductId(product.getProductId());
        return productSellInfo;
    }

    @Override
    public ProductSellInfo getProductById(Integer productId) {
        String productHashKey = PRODUCT_HASH_PREFIX + productId;

        HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash();
        Map<String, Object> entries = hashOps.entries(productHashKey);

        if (redisTemplate.hasKey(productHashKey)) {

            ProductSellInfo productSellInfo = new ProductSellInfo();

            Object productIdObj = entries.get("productId");
            if(productIdObj instanceof String) {
                productSellInfo.setProductId(Integer.parseInt((String)productIdObj));
            } else if (productIdObj instanceof Integer) {
                productSellInfo.setProductId((Integer) productIdObj);
            }
            //productSellInfo.setProductId((Integer) entries.get("productId"));
            productSellInfo.setProductName((String) entries.get("productName"));
            productSellInfo.setProductDescription((String) entries.get("productDescription"));
            productSellInfo.setProductPrice(new BigDecimal((String) entries.get("productPrice")));

            Object productStockObj = entries.get("productStock");
            if(productStockObj instanceof String) {
                productSellInfo.setProductStock(Integer.parseInt((String)productStockObj));
            } else if (productStockObj instanceof Integer) {
                productSellInfo.setProductStock((Integer) productStockObj);
            }
            //productSellInfo.setProductStock((Integer) entries.get("productStock"));

            Object categoryIdObj = entries.get("categoryId");
            if(categoryIdObj instanceof String) {
                productSellInfo.setCategoryId(Integer.parseInt((String)categoryIdObj));
            } else if (categoryIdObj instanceof Integer) {
                productSellInfo.setCategoryId((Integer) categoryIdObj);
            }
            //productSellInfo.setCategoryId((Integer) entries.get("categoryId"));

            Object shopIdObj = entries.get("shopId");
            if(shopIdObj instanceof String) {
                productSellInfo.setShopId(Integer.parseInt((String)shopIdObj));
            } else if (shopIdObj instanceof Integer) {
                productSellInfo.setShopId((Integer) shopIdObj);
            }

            //productSellInfo.setShopId((Integer) entries.get("shopId"));

            productSellInfo.setProductCoverImage((String) entries.get("productCoverImage"));

            String productImageSetKey = PRODUCT_IMAGE_HASH_PREFIX + productId;
            ZSetOperations<String, String> productImageSetOps = redisTemplate.opsForZSet();
            Set<ZSetOperations.TypedTuple<String>> productImageSets = productImageSetOps.rangeWithScores(productImageSetKey, 0, -1);
            if (productImageSets != null && !productImageSets.isEmpty()) {
                for (ZSetOperations.TypedTuple<String> productImageSet : productImageSets) {
                    String imageUrl = productImageSet.getValue();
                    productSellInfo.getProductImageList().add(imageUrl);

                    System.out.println(imageUrl);

                    productSellInfo.getProductImageListOrder().add(productImageSet.getScore().intValue());
                }
            }
//            productSellInfo.setProductImageListOrder(new ArrayList<>());
//            productSellInfo.setProductImageList(new ArrayList<>());
            return productSellInfo;
        }

        Product product = productMapper.selectByPrimaryKey(productId);
        if (product == null) {
            return null;
        }
        ProductSellInfo productSellInfo = new ProductSellInfo();
        productSellInfo.setProductId(product.getProductId());
        productSellInfo.setProductName(product.getProductName());
        productSellInfo.setProductDescription(product.getProductDescription());
        productSellInfo.setProductPrice(product.getProductPrice());
        productSellInfo.setProductStock(product.getProductStock());
        productSellInfo.setCategoryId(product.getCategoryId());
        productSellInfo.setShopId(product.getShopId());
        productSellInfo.setProductCoverImage(product.getProductCoverImage());


        ProductImageExample productImageExample = new ProductImageExample();
        productImageExample.createCriteria().andProductIdEqualTo(product.getProductId());
        List<ProductImage> productImages = productImageMapper.selectByExample(productImageExample);
        productImages.forEach(productImage -> {
            productSellInfo.getProductImageList().add(productImage.getImageUrl());

            System.out.println(productImage.getImageUrl());

            productSellInfo.getProductImageListOrder().add(productImage.getSortOrder());
        });

        productSellInfo.setProductOnlineStatus(product.getProductIsOnline() ? 1 : 0);

        redisTemplate.opsForHash().putAll(productHashKey, Map.of(
                "productId", product.getProductId(),
                "productName", product.getProductName(),
                "productDescription", product.getProductDescription(),
                "productPrice", product.getProductPrice().toString(),
                "productStock", product.getProductStock(),
                "categoryId", product.getCategoryId(),
                "shopId", product.getShopId(),
                "productCoverImage", product.getProductCoverImage(),
                "productIsOnline", product.getProductIsOnline().toString()
        ));

        String imageSetKey = "product:image:" + productId.toString();
        ZSetOperations<String, String> zSetOps = redisTemplate.opsForZSet();
        redisTemplate.delete(imageSetKey);

        List<String> productImageList = productSellInfo.getProductImageList();
        List<Integer> productImageListOrder = productSellInfo.getProductImageListOrder();
        for (int i = 0; i < productImageList.size(); i++) {
            zSetOps.add(imageSetKey, productImageList.get(i), (double) productImageListOrder.get(i));
        }
        redisTemplate.expire(imageSetKey, 10, TimeUnit.MINUTES);

        redisTemplate.expire(productHashKey, 10, TimeUnit.MINUTES);

        return productSellInfo;

    }

    @Override
    public String updateProductOnlineStatus(Integer productId, Integer productOnlineStatus) {
        //  参数校验
        if (productId == null || productOnlineStatus == null) {
            return "参数缺失";
        }
        if (productOnlineStatus != 0 && productOnlineStatus != 1) {
            return "非法的上下架状态";
        }

        // 查询商品
        Product product = productMapper.selectByPrimaryKey(productId);
        if (product == null) {
            return "商品不存在";
        }

        // 更新数据库
        product.setProductIsOnline(productOnlineStatus == 1);
        productMapper.updateByPrimaryKeySelective(product);

        String productHashKey = PRODUCT_HASH_PREFIX + productId;
        // 更新 Redis Hash 中的状态，并设置过期时间
        redisTemplate.opsForHash().put(productHashKey, "productIsOnline", productOnlineStatus == 1);
        redisTemplate.expire(productHashKey, 10, TimeUnit.MINUTES);

        // 更新分类和卖家集合
        if (productOnlineStatus == 0) {
            // 下架：从分类和卖家集合中移除
            String categoryKey = "product:category:" + product.getCategoryId() + ":ids";
            redisTemplate.opsForSet().remove(categoryKey, productId.toString());

//            String sellerKey = "product:seller:" + product.getSellerId() + ":ids";
//            redisTemplate.opsForSet().remove(sellerKey, productId.toString());


        } else {
            // 上架：加入分类和卖家集合
            String categoryKey = "product:category:" + product.getCategoryId() + ":ids";
            redisTemplate.opsForSet().add(categoryKey, productId.toString());
            redisTemplate.expire(categoryKey, 10, TimeUnit.MINUTES); // 统一过期时间

//            String sellerKey = "product:seller:" + product.getSellerId() + ":ids";
//            redisTemplate.opsForSet().add(sellerKey, productId.toString());
//            redisTemplate.expire(sellerKey, 10, TimeUnit.MINUTES);
        }
        redisTemplate.delete("product:online:list");
        return productOnlineStatus == 1 ? "上架成功" : "下架成功";
    }

    @Override
    public String updateProductAuditStatus(Integer productId, Integer productAuditStatus, String username) {
        return "";
    }

    // 定时任务刷新缓存
//    @Scheduled(fixedRate = 100000)
//    @CacheEvict(value = "productCache", allEntries = true)
//    public void refreshProductCache() {
//        System.out.println("刷新缓存");
//    }

    //关键词查询商品
//    @Cacheable(value = "productCache", key = "#productName")
    @Override
    public List<ProductSellInfo> selectProductByKeyWord(String productName) {

        String encode = URLEncoder.encode(productName, StandardCharsets.UTF_8).replace("+", "%20");
        ;
        String searchKey = "product:search:" + encode + ":ids";

        SetOperations<String, String> setOperations = redisTemplate.opsForSet();
        Set<String> cachedProductIds = setOperations.members(searchKey);

        if (cachedProductIds != null && !cachedProductIds.isEmpty()) {
            List<ProductSellInfo> productSellInfos = cachedProductIds.stream().map(productId -> {
                String productHashKey = PRODUCT_HASH_PREFIX + productId;
                HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash();
                Map<String, Object> entries = hashOps.entries(productHashKey);

                ProductSellInfo productSellInfo = new ProductSellInfo();
                productSellInfo.setProductId((Integer) entries.get("productId"));
                productSellInfo.setProductName((String) entries.get("productName"));
                productSellInfo.setProductDescription((String) entries.get("productDescription"));
                productSellInfo.setProductPrice(new BigDecimal((String) entries.get("productPrice")));
                productSellInfo.setProductStock((Integer) entries.get("productStock"));
                productSellInfo.setCategoryId((Integer) entries.get("categoryId"));
                productSellInfo.setShopId((Integer) entries.get("shopId"));
                productSellInfo.setProductCoverImage((String) entries.get("productCoverImage"));

                return productSellInfo;
            }).toList();
            return productSellInfos;
        }


        ProductExample example = new ProductExample();
        example.createCriteria().andProductNameLike("%" + productName + "%");
        List<Product> products = productMapper.selectByExample(example);
        if (!products.isEmpty()) {
            List<ProductSellInfo> productSellInfos = products.stream().map(product -> {
                if (product.getProductIsOnline()) { // 判断商品是否上架
                    ProductSellInfo productSellInfo = new ProductSellInfo();
                    productSellInfo.setProductId(product.getProductId());
                    productSellInfo.setProductName(product.getProductName());
                    productSellInfo.setProductDescription(product.getProductDescription());
                    productSellInfo.setProductPrice(product.getProductPrice());
                    productSellInfo.setProductStock(product.getProductStock());
                    productSellInfo.setCategoryId(product.getCategoryId());
                    productSellInfo.setShopId(product.getShopId());
                    productSellInfo.setProductCoverImage(product.getProductCoverImage());
                    productSellInfo.setProductOnlineStatus(product.getProductIsOnline() ? 1 : 0);
                    return productSellInfo;
                }
                return null;
            }).toList();

            if (productSellInfos.isEmpty()) {
                // 缓存空值防穿透
                redisTemplate.opsForSet().add(searchKey, "EMPTY");
                redisTemplate.expire(searchKey, 1, TimeUnit.MINUTES);
            } else {
                for (Product product : products) {
                    if (product.getProductIsOnline()) {
                        String productHashKey = PRODUCT_HASH_PREFIX + product.getProductId();
                        redisTemplate.opsForHash().putAll(productHashKey, Map.of(
                                "productId", product.getProductId().toString(),
                                "productName", product.getProductName(),
                                "productDescription", product.getProductDescription(),
                                "productPrice", product.getProductPrice().toString(),
                                "productStock", product.getProductStock().toString(),
                                "categoryId", product.getCategoryId().toString(),
                                "shopId", product.getShopId().toString(),
                                "productCoverImage", product.getProductCoverImage(),
                                "productIsOnline", product.getProductIsOnline().toString()
                        ));
                        redisTemplate.expire(productHashKey, 10, TimeUnit.MINUTES);
                        return productSellInfos;
                    }
                }
            }
            return productSellInfos;
        }
        return List.of();
    }

    //    @Cacheable(value = "productCache", key = "#root.methodName") // 使用方法名作为key
//    @Override
//    public List<ProductSellInfo> outputProduct() {
//
//        ProductExample example = new ProductExample();
//        example.setOrderByClause("RAND()"); // 添加随机排序
//
//        List<ProductSellInfo> productSellInfos = productMapper.selectByExample(example).stream()
//                .filter(product -> Boolean.TRUE.equals(product.getProductIsOnline())) // 过滤出已上架的商品
//                .map(product -> {
////                    redisTemplate.opsForHash().put(PRODUCT_DETAIL_KEY + product.getProductId(), product.getProductId().toString(), JSONObject.toJSONString(product));
//                    ProductSellInfo productSellInfo = new ProductSellInfo();
//                    productSellInfo.setProductId(product.getProductId());
//                    productSellInfo.setProductName(product.getProductName());
//                    productSellInfo.setProductDescription(product.getProductDescription());
//                    productSellInfo.setProductPrice(product.getProductPrice());
//                    productSellInfo.setProductStock(product.getProductStock());
//                    productSellInfo.setCategoryId(product.getCategoryId());
//                    productSellInfo.setSellerId(product.getSellerId());
//                    productSellInfo.setProductCoverImage(product.getProductCoverImage());
//                    return productSellInfo;
//                })
//                .toList(); // 收集结果为列表
//        return productSellInfos; // 返回实际的结果列表
//    }
    @Override
    public List<ProductSellInfo> outputProduct() {
        String cacheKey = "product:online:list"; // 缓存所有已上架商品
        ValueOperations<String, String> valueOps = redisTemplate.opsForValue();
        ObjectMapper objectMapper = new ObjectMapper(); // Jackson 序列化工具

        try {
            // 尝试从缓存读取
            String cachedJson = valueOps.get(cacheKey);
            if (cachedJson != null) {
                List<ProductSellInfo> cachedList = objectMapper.readValue(cachedJson, new TypeReference<List<ProductSellInfo>>() {
                });
                Collections.shuffle(cachedList); // 应用层随机打乱顺序
                return cachedList;
            }

            // 缓存未命中，查询数据库
            ProductExample example = new ProductExample();
            // 查询全部已上架商品
            example.createCriteria().andProductIsOnlineEqualTo(true);

            List<ProductSellInfo> productSellInfos = productMapper.selectByExample(example).stream()
                    .map(product -> {
                        ProductSellInfo productSellInfo = new ProductSellInfo();
                        productSellInfo.setProductId(product.getProductId());
                        productSellInfo.setProductName(product.getProductName());
                        productSellInfo.setProductDescription(product.getProductDescription());
                        productSellInfo.setProductPrice(product.getProductPrice());
                        productSellInfo.setProductStock(product.getProductStock());
                        productSellInfo.setCategoryId(product.getCategoryId());
                        productSellInfo.setShopId(product.getShopId());
                        productSellInfo.setProductCoverImage(product.getProductCoverImage());
                        return productSellInfo;
                    })
                    .collect(Collectors.toList());

            // 写入缓存JSON 序列化
            if (!productSellInfos.isEmpty()) {
                String json = objectMapper.writeValueAsString(productSellInfos);
                valueOps.set(cacheKey, json, 5, TimeUnit.MINUTES);
            } else {
                valueOps.set(cacheKey, "[]", 1, TimeUnit.MINUTES);
            }

            // 返回前随机排序
            Collections.shuffle(productSellInfos);
            return productSellInfos;
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Redis 序列化异常", e);
        }
    }


    //    @Cacheable(value = "productCache", key = "#root.methodName")
    @Override
    public List<ProductSellInfo> outputAllProduct() {

        String allProductSetKey = "product:all:ids";
        HashOperations hashOperations = redisTemplate.opsForHash();
        SetOperations setOperations = redisTemplate.opsForSet();

        if (redisTemplate.hasKey(allProductSetKey)) {
            Set<Integer> productIds = setOperations.members(allProductSetKey);
            List<ProductSellInfo> productSellInfos = productIds.stream()
                    .map(id -> {
                        String productHashKey = "product:" + id;
                        Map entries = hashOperations.entries(productHashKey);
                        if (entries.isEmpty()) {
                            return null;
                        } else {
                            ProductSellInfo productSellInfo = new ProductSellInfo();
                            productSellInfo.setProductId((Integer) entries.get("productId"));
                            productSellInfo.setProductName((String) entries.get("productName"));
                            productSellInfo.setProductDescription((String) entries.get("productDescription"));
                            productSellInfo.setProductPrice((BigDecimal) entries.get("productPrice"));
                            productSellInfo.setProductStock((Integer) entries.get("productStock"));
                            productSellInfo.setCategoryId((Integer) entries.get("categoryId"));
                            productSellInfo.setShopId((Integer) entries.get("shopId"));
                            productSellInfo.setProductCoverImage((String) entries.get("productCoverImage"));
                            productSellInfo.setProductOnlineStatus((Integer) entries.get("productIsOnline"));
                            return productSellInfo;
                        }
                    })
                    .collect(Collectors.toList());
            return productSellInfos;
        } else {

            List<ProductSellInfo> productSellInfos = productMapper.selectByExample(new ProductExample()).stream()
                    .map(product -> {
                        ProductSellInfo productSellInfo = new ProductSellInfo();
                        productSellInfo.setProductId(product.getProductId());
                        productSellInfo.setProductName(product.getProductName());
                        productSellInfo.setProductDescription(product.getProductDescription());
                        productSellInfo.setProductPrice(product.getProductPrice());
                        productSellInfo.setProductStock(product.getProductStock());
                        productSellInfo.setCategoryId(product.getCategoryId());
                        productSellInfo.setShopId(product.getShopId());
                        productSellInfo.setProductCoverImage(product.getProductCoverImage());
                        productSellInfo.setProductOnlineStatus(
                                Boolean.TRUE.equals(product.getProductIsOnline()) ? 1 : 0
                        );
                        return productSellInfo;
                    })
                    .toList(); // 收集结果为列表
            if (productSellInfos.isEmpty()) {
                setOperations.add(allProductSetKey, "EMPTY");
                redisTemplate.expire(allProductSetKey, 1, TimeUnit.MINUTES);
                return List.of();
            } else {
                for (ProductSellInfo productSellInfo : productSellInfos) {
                    String productHashKey = PRODUCT_HASH_PREFIX + productSellInfo.getProductId().toString();
                    setOperations.add(allProductSetKey, productSellInfo.getProductId().toString());
                    hashOperations.putAll(productHashKey, Map.of(
                            "productId", productSellInfo.getProductId().toString(),
                            "productName", productSellInfo.getProductName(),
                            "productDescription", productSellInfo.getProductDescription(),
                            "productPrice", productSellInfo.getProductPrice().toString(),
                            "productStock", productSellInfo.getProductStock().toString(),
                            "categoryId", productSellInfo.getCategoryId().toString(),
                            "shopId", productSellInfo.getShopId().toString(),
                            "productCoverImage", productSellInfo.getProductCoverImage(),
                            "productIsOnline", productSellInfo.getProductOnlineStatus()
                    ));
                    redisTemplate.expire(productHashKey, 5, TimeUnit.MINUTES);
                }

            }
            return productSellInfos; // 返回实际的结果列表
        }
    }


}
